#define JMBC_INSIDE
#include "ilImage.h"
#include <Math/mlMath.h>
#include <Core/clCore.h>
#include <stdio.h>
#include <GL/glu.h>

// Context

#define STORE ID_SMALL_STORE

static ILImage *store[STORE];

void
ilImageCreateContext(void)
{
	idClearStore(ILImage, STORE, store);
}

ILImage *
ilImageStore(unsigned int id)
{
	return store[id];
}

// Generation / Deletion

static
void
Init(ILImage *image)
{
}

static
void
Term(ILImage *image)
{
}

void
ilGenImages(unsigned int n, unsigned int *images)
{
	idGenObjects(ILImage, STORE, store, Init, n, images);
}

void
ilDeleteImages(unsigned int n, unsigned int *images)
{
	idDeleteObjects(store, Term, n, images);
}

// Load / Unload

void
ilImageLoad(unsigned int id, unsigned int filepath)
{
	unsigned int strings[3], elError;

	tlGenStrings(2, &strings[1]);

	strings[0] = filepath;

	tlStringLoad(strings[1], L".png");
	tlStringConcat(strings[2], 2, strings);
	ilImageLoadPNG(id, strings[2]);
	elError = elErrorGet();
	tlStringsUnload(2, &strings[1]);

	if(elError != EL_ERROR_NONE)
	{
		elErrorSet(EL_ERROR_NONE);

		tlStringLoad(strings[1], L".jpg");
		tlStringConcat(strings[2], 2, strings);
		ilImageLoadJPG(id, strings[2]);
		elError = elErrorGet();
		tlStringsUnload(2, &strings[1]);

		if(elError != EL_ERROR_NONE)
		{
			elErrorSet(EL_ERROR_NONE);

			tlStringLoad(strings[1], L".tga");
			tlStringConcat(strings[2], 2, strings);
			ilImageLoadTGA(id, strings[2]);
			tlStringsUnload(2, &strings[1]);
		}
	}

	tlDeleteStrings(2, &strings[1]);
}


void
ilImageUnload(unsigned int id)
{
	ILImage *image;

	image = store[id];

	free(image->pixels);
}

void
ilImagesUnload(unsigned int n, unsigned int *images)
{
	unsigned int i;

	for(i = 0; i < n; i++)
		ilImageUnload(images[i]);
}

// OpenGL Integration

GLenum
ilImageBPPToFormat(unsigned int bpp)
{
	GLenum format = GL_RGB;

	switch(bpp)
	{
		case 3: format = GL_RGB; break;
		case 4: format = GL_RGBA; break;
		default: elErrorSet(EL_ERROR_INVALID); break;
	}

	return format;
}

unsigned int
ilImageFormatToBPP(GLenum format)
{
	unsigned int bpp;

	switch(format)
	{
		case GL_RGB: bpp = 3; break;
		case GL_RGBA: bpp = 4; break;
	}

	return bpp;
}

// OpenGL Integration

void
ilImageCapture(unsigned int id, int x, int y, unsigned int width, unsigned int height, GLenum format)
{
	ILImage *image;

	image = store[id];

	image->width = width;
	image->height = height;
	image->bpp = ilImageFormatToBPP(format);
	image->pixels = malloc(image->width * image->height * image->bpp * sizeof(unsigned char));

	glReadPixels(x, y, image->width, image->height, format, GL_UNSIGNED_BYTE, image->pixels);
}

void
ilImageBuild2DMipmaps(unsigned int id)
{
	ILImage *image;

	image = store[id];

	gluBuild2DMipmaps(GL_TEXTURE_2D, ilImageBPPToFormat(image->bpp), image->width, image->height, ilImageBPPToFormat(image->bpp), GL_UNSIGNED_BYTE, image->pixels);
}

void
ilImageTexImage2D(unsigned int id)
{
	ILImage *image;

	image = store[id];

	glTexImage2D(GL_TEXTURE_2D, 0, ilImageBPPToFormat(image->bpp), image->width, image->height, 0, ilImageBPPToFormat(image->bpp), GL_UNSIGNED_BYTE, image->pixels);
}
